package com.dmx.fw.resource;

import java.util.HashMap;

import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.log4j.Logger;

import com.dmx.fw.exception.GeneralException;
import com.dmx.fw.util.StrUtils;


/**
 * JNDI资源工厂，通过这个类提供的接口获得系统JNDI服务器提供的JNDI对象
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: </p>
 * @author not attributable
 * @version 1.0
 */
public class JndiFactory {
    //jndi对象缓存
	private static HashMap jndiMap = new HashMap();
    private final static Logger log =Logger.getLogger(JndiFactory.class);
    
    private static DataSource springDs;

    /**
     * 通过JNDI查找数据源对象
     * @param jndiName
     * @return
     * @throws java.lang.Exception
     */
    public static DataSource getDataSource(String jndiName) throws Exception {
    	//使用spring的datasource
    	return springDs;
    	/*if (StrUtils.isNullOrEmpty(jndiName)){
    		jndiName = SystemProperties.getInstance().getDataSourceJndiName();
    		//if (StrUtils.isNullOrEmpty(jndiName)){
    		//	jndiName = "java:/comp/env/jdbc/moss";
    		//}
    		
    	}
        try {
            return (DataSource)lookup(jndiName);
        } catch(GeneralException e){
        	log.error(e);
            //throw e;
        	return springDs;
        }*/
    }
    
    /**
     * 获得系统缺省数据源
     * @return
     * @throws Exception
     */
    public static DataSource getDataSource() throws Exception {
    	return getDataSource(null);
    }


    public static DataSource getDataSource(String jndiName,boolean bNew)
                                              throws Exception {
    	if (StrUtils.isNullOrEmpty(jndiName)){
    		jndiName = SystemProperties.getInstance().getDataSourceJndiName();
    	}    	
        if (bNew)
            clearJNDIByName(jndiName);
        return getDataSource(jndiName);
    }

    /**
     * 通过JNDI名字删除缓存的JNDI对象
     * @param jndiName
     */
    private static void clearJNDIByName(String jndiName){
        try {
            if (jndiMap==null)
                return;
            if (jndiMap.get(jndiName)==null)
                return;
            synchronized(jndiMap){
                jndiMap.remove(jndiName);
            }
        } catch(Exception e){
        	log.error(e);
        }
    }

    /**
     * 查找jndi对象
     * @param jndiName
     * @return
     * @throws java.lang.Exception
     */
    public static Object lookup(String jndiName) throws Exception{
    	Object jndiObj = jndiMap.get(jndiName);
    	if (jndiObj!=null)
    		return jndiObj;
    	
        try{ 	
			Context ct = ContextMg.getContext(null);
			jndiObj = ct.lookup(jndiName);
			if (jndiObj!=null){
                synchronized (jndiMap){
                	jndiMap.put(jndiName,jndiObj);
                }
			}
        }catch(NamingException e){
        	log.error(e);
            throw e;
        }
        return jndiObj;
    }

    public static Object lookup(String jndiName,boolean bNew) throws Exception{
        if (bNew)
            clearJNDIByName(jndiName);
        return lookup(jndiName);
    }


    /****************************************************************
     * 打印jndi信息
     * @param name
     * @param dir
     * @param numLevelsDeep
     ****************************************************************/

    public static void printContext(String name, Context dir, int numLevelsDeep){
       Binding             item = null;
       NamingEnumeration   enumObj = null;
       try {
           // If a binding name was given, use that as the starting point,
           // otherwise start from the root
           if ( null != name )
        	   enumObj = dir.listBindings(name);
           else
        	   enumObj = dir.listBindings("");
           // If you have not reached the end of the binding tree, keep looping through it
           while (enumObj.hasMore()) {
               try {

                   // Retrieve the Binding from the context
                   item = (Binding) enumObj.next();

                   // For each subcontext that you have entered there should be a blank tab in it's
                   // place to visually show the structure hierarchy.
                   for (int i = 0; i < numLevelsDeep; i++)
                       System.out.print("    ");

                   // If the object returned is a Context print it's name along with a '/'
                   // and then run the printContext routine again and increment the level counter
                   // and move to the next Subcontext using that subcontexts binding name as a starting point
                   if (item.getObject() instanceof Context) {
                       Context subContext = (Context) item.getObject();
                       System.out.println(item.getName()+"/");
                       printContext(null,subContext, numLevelsDeep + 1);
                   } else {
                       // Otherwise print the name of the Object (Non-context) that was returned
                       // This is the actual Java Object that is retured (Class, JDBC Connection Pool, etc..)
                       Object  ab = (Object) item.getObject();
                       System.out.println(item.getName());
                   }
               } catch (NamingException e) {
                   System.out.println("Inner Exception");
                   System.out.println(e);
               }
           }
       } catch (NamingException e) {
           System.out.println(e);
       }
   }

	public DataSource getSpringDs() {
		return springDs;
	}

	public void setSpringDs(DataSource springDs) {
		this.springDs = springDs;
	}

}
